home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / tools / net-tools / amitrack / source / amitrack.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-16  |  32.9 KB  |  1,012 lines

  1. /* AmiTrack.c -- a program to keep a running list of available Amigas. */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <time.h>
  7.  
  8. #include <exec/types.h>
  9. #include <exec/io.h>
  10. #include <exec/lists.h>
  11. #include <exec/memory.h>
  12.  
  13. #include <clib/exec_protos.h>
  14. #include <clib/alib_protos.h>
  15. #include <clib/dos_protos.h>
  16. #include <clib/socket_protos.h>
  17.  
  18. #include <errno.h>
  19. #include <inetd.h>
  20. #include <sys/types.h>
  21.  
  22. #include <proto/socket.h>
  23. #include <proto/exec.h>
  24. #include <sys/errno.h>
  25. #include <sys/types.h>
  26. #include <sys/socket.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/syslog.h>
  29. #include <netdb.h>
  30.  
  31.  
  32. #include <intuition/intuition.h>
  33. #include <intuition/intuitionbase.h>
  34. #include <intuition/gadgetclass.h>
  35. #include <intuition/screens.h>
  36. #include <libraries/gadtools.h>
  37. #include <clib/icon_protos.h>
  38. #include <clib/wb_protos.h>
  39. #include <clib/intuition_protos.h>
  40. #include <clib/diskfont_protos.h>
  41. #include <clib/gadtools_protos.h>
  42. #include <clib/graphics_protos.h>
  43.  
  44. #include <pragmas/socket_pragmas.h>
  45. #include <devices/timer.h>
  46.  
  47. #include "AmiTrackShared.h"
  48.  
  49. #define MAX_PING_ERRORS        5
  50. #define DEFAULT_PING_DELAY    1
  51. #define DEFAULT_REFRESH_DELAY    5
  52. #define DEFAULT_AMITRACK_SERVER ""
  53.  
  54. struct Library * SocketBase = NULL;
  55.  
  56. struct timerequest *TimerIO  = NULL;
  57. struct MsgPort       *TimerMP  = NULL;
  58. struct Message       *TimerMSG = NULL;
  59.  
  60. BOOL BStartedFromWB = FALSE;
  61. BOOL BSendGoodbye = FALSE;    /* TRUE if we think we have a live server, else FALSE */
  62. int nPort = SERVER_TCP_PORT;
  63. int nPingInterval = DEFAULT_PING_DELAY, nRefreshInterval = DEFAULT_REFRESH_DELAY;
  64. int nPingCount    = DEFAULT_PING_DELAY, nRefreshCount    = DEFAULT_REFRESH_DELAY;
  65. struct SocketStuff * UDPSocket = NULL;
  66. struct TimerStuff  * Timer = NULL;
  67. char * szCurrentHostname = NULL, * szCurrentComment = NULL;
  68. char szMyHostName[100];
  69. ULONG ulMyIPAddress = 0L;
  70. char szVersionString[] = "$VER: AmiTrack v1.1", * pcDisplayVersionString;
  71. void BeAClient(char * szHostName, char * szComment, int nPort);
  72. void Cleanup(void);
  73. void debug(int n);
  74. BOOL SendPacket(struct SocketStuff * sSocket, ULONG ulReqs, char * szComment);
  75. BOOL ConnectToServer(struct WindowStuff *, struct SocketStuff *, char * szPeerName);
  76. BOOL PingServer(struct WindowStuff * win, struct SocketStuff * sSocket, char * szComment);
  77. void DoPeriodicUpdates(struct WindowStuff * win, struct SocketStuff * sSocket, struct TimerStuff * timer);
  78. int main(int argc, char **argv);
  79.  
  80.  
  81. /* Data structures for Gadtools GUI */
  82. struct Library * WorkbenchBase = NULL;
  83. struct Library * IconBase      = NULL;
  84. struct Library * GraphicsBase  = NULL;
  85. struct Library * IntuitionBase = NULL;
  86. struct Library * GadToolsBase  = NULL;
  87. struct Library * DiskFontBase  = NULL;
  88.  
  89. struct WindowStuff * TrackWindow   = NULL;
  90. struct Menu     *Menu     = NULL;
  91. struct MenuItem *MenuItem = NULL;
  92.  
  93. /* GUI settings */
  94. int nWinLeft        = 50;
  95. int nWinTop        = 100;
  96. int nWinWidth        = 520;
  97. int nWinHeight        = 200;
  98. int nMinWinWidth    = 300;
  99. int nMinWinHeight    = 120;
  100.  
  101. #define P_ICONIFY 100
  102. #define P_ABOUT   101
  103. #define P_QUIT    102
  104.  
  105. /* menus */
  106. struct NewMenu nmMenus[] = {
  107.     NM_TITLE, "Project",      NULL,     0L,             NULL, NULL,
  108.     NM_ITEM,  "About",          "O",    0L,         NULL, (void *) P_ABOUT,
  109.     NM_ITEM,  "Iconify",      "I",    0L,         NULL, (void *) P_ICONIFY,
  110.     NM_ITEM,  NM_BARLABEL,      NULL,     0L,             NULL, NULL,
  111.     NM_ITEM,  "Quit",            "Q",      0L,             NULL, (void *) P_QUIT,
  112.     NM_END,   NULL,          NULL,     NULL,             NULL, NULL
  113. };
  114.  
  115.  
  116.  
  117. /* GUI functions */
  118. struct WindowStuff * SetupTrackWindow(struct WindowStuff *);
  119. ULONG HandleIDCMP(struct WindowStuff *);
  120. BOOL UpdateWindow(struct WindowStuff * win, BOOL BFree);
  121. struct Node * AllocDisplayItem(char * szHostName, ULONG ulIPAddress, ULONG ulHostFieldLen, char * szComment);
  122. void FreeDisplayList(struct List * list);
  123. void SetConnectStatus(struct WindowStuff * win, BOOL BNewStatus);
  124. void StatMessage(char *);
  125. void FreeDisplayItem(struct Node * current);
  126. void AttachList(struct WindowStuff * win, BOOL BAttach);
  127. void PatchDisplayList(struct List * DisplayList, ULONG ulIPAddress, char * szReplaceMe, char * szNewComment);
  128. struct WindowStuff * Hibernate(struct WindowStuff *, struct SocketStuff * sSocket, struct TimerStuff * timer);
  129. BOOL CreateTrackMenus(struct WindowStuff * win, BOOL BCreate);
  130.  
  131. /* ------------ Amiga GUI functions -------------------------- */
  132.  
  133. #define HSPACE             5
  134. #define VSPACE             5
  135. #define PING_BUTTON_TEXT     "_Ping"
  136. #define UPDATE_BUTTON_TEXT     "_Refresh"
  137. #define SERVER_STRING_TEXT     "_Server:"
  138. #define PORT_STRING_TEXT     "P_ort:"
  139. #define COMMENT_STRING_TEXT     "_Comment:"
  140. #define EVERY_TEXT         "every"
  141. #define MINS_TEXT1         "_minutes,"
  142. #define MINS_TEXT2         "m_inutes."
  143. #define ALL_BOTTOM_LINE_TEXT    "Refresh every 888 minutes, Ping every 888 minutes."
  144.  
  145.  
  146. /* Iconify yourself and don't wake up until... */
  147. struct WindowStuff * Hibernate(struct WindowStuff *win, struct SocketStuff * sSocket, struct TimerStuff * timer)
  148. {
  149.     int nCode;
  150.     struct MsgPort        *myport      = NULL;
  151.     struct AppIcon        *appicon     = NULL;
  152.     struct AppMessage    *amsg          = NULL;
  153.     struct DiskObject     *appIconObj     = NULL;
  154.     struct List * saveDisplayList;
  155.     
  156.     /* backup--use default icon */
  157.     UNLESS(appIconObj = GetDefDiskObject(WBTOOL)) return(win);
  158.     appIconObj->do_Type = 0L;
  159.     
  160.     if (myport = CreateMsgPort())
  161.     {
  162.         if (appicon = AddAppIconA(0L, 0L, "AmiTrack", myport, NULL, appIconObj, NULL))
  163.         {
  164.             /* Save the display list! */
  165.             saveDisplayList = win->DisplayList;
  166.             win->DisplayList = NULL;
  167.             
  168.             SetupTrackWindow(win);
  169.             while(1)
  170.             {
  171.                 nCode = TrackWait(NULL, NULL, Timer, NULL, myport);
  172.                 if (nCode & CODE_TIMER_EXPIRED) DoPeriodicUpdates(TrackWindow, sSocket, timer);
  173.                 if (nCode & CODE_MSGPORT) break;
  174.                 if (nCode == 0) break;
  175.             }
  176.             RemoveAppIcon(appicon);
  177.             win = SetupTrackWindow(NULL);
  178.             AttachList(win,FALSE);
  179.             win->DisplayList = saveDisplayList;
  180.             AttachList(win,TRUE);
  181.         }
  182.         /* Remove any pending messages */
  183.         Forbid(); 
  184.          while (amsg = (struct AppMessage *) GetMsg(myport)) ReplyMsg((struct Message *)amsg); 
  185.          DeleteMsgPort(myport);
  186.         Permit();
  187.         
  188.         FreeDiskObject(appIconObj);
  189.     }
  190.     return(win);
  191. }
  192.  
  193. /* To tear down, set BCreate==FALSE */
  194. BOOL CreateTrackMenus(struct WindowStuff * win, BOOL BCreate)
  195. {   
  196.     UNLESS((win)&&(win->vi)) return(FALSE);
  197.     
  198.     UNLESS(BCreate) 
  199.     {
  200.         if (Menu) 
  201.         {
  202.             ResetMenuStrip(win->win,Menu); 
  203.             FreeMenus(Menu); 
  204.             Menu = NULL;
  205.         }
  206.         return(FALSE);
  207.     }
  208.  
  209.     /* Create menus */
  210.     UNLESS((Menu = CreateMenus(nmMenus, TAG_DONE)) &&
  211.            (LayoutMenus(Menu, win->vi, TAG_DONE)))
  212.            return(CreateTrackMenus(win, FALSE));
  213.  
  214.     SetMenuStrip(win->win, Menu);
  215.     return(TRUE);
  216. }
  217.  
  218. /* Updates/reupdates the window on creation or after a size change */
  219. /* If BFree is TRUE, just deallocate anything that was allocated */
  220. /* Returns the allocated/deallocated state of the window gadgets */
  221. BOOL UpdateWindow(struct WindowStuff * win, BOOL BFree)
  222. {
  223.     int nID = 0;
  224.     struct NewGadget ng;
  225.     struct Gadget * gad;
  226.     
  227.     UNLESS((win)&&(win->screen)) return(FALSE);
  228.     /* First deallocate */
  229.     if ((win->win)&&(win->glist)) RemoveGList(win->win, win->glist, -1);
  230.     if (win->glist)    {FreeGadgets(win->glist); win->glist = NULL;}
  231.  
  232.     /* Mark all gadgets as free */
  233.     win->ListGadget    = win->PingButton    =
  234.     win->UpdateButton  = win->ServerString  = 
  235.     win->PortString    = win->CommentString =
  236.     win->UpdateIntString = win->PingIntString =  NULL;
  237.  
  238.     if (Menu) CreateTrackMenus(win, FALSE);
  239.     if (win->vi) {FreeVisualInfo(win->vi); win->vi = NULL;}
  240.     if (BFree) return(FALSE);    /* If we're just freeing, that's all to do */
  241.  
  242.     if (win->win)
  243.     {
  244.         /* erase any gadget imagery */
  245.         EraseRect(win->win->RPort,win->win->BorderLeft, win->win->BorderTop,
  246.           win->win->Width - win->win->BorderRight - 1,
  247.                   win->win->Height - win->win->BorderBottom - 1);
  248.         RefreshWindowFrame(win->win);               
  249.     }
  250.  
  251.     /* Make everything NULL, etc. */
  252.     memset(&ng, 0, sizeof(ng));
  253.  
  254.     /* Now start allocating */
  255.     UNLESS(win->vi = GetVisualInfo(win->screen,TAG_END)) return(FALSE);
  256.     UNLESS(CreateTrackMenus(win, TRUE))             return(FALSE);
  257.     UNLESS(gad     = CreateContext(&win->glist))         return(FALSE);
  258.     
  259.     /* Allocate Server gadget */
  260.     ng.ng_VisualInfo = win->vi;
  261.     ng.ng_TextAttr   = &win->font;
  262.     ng.ng_Height     = win->font.ta_YSize + VSPACE;
  263.     ng.ng_GadgetText = SERVER_STRING_TEXT;
  264.     ng.ng_LeftEdge   += win->screen->WBorLeft + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
  265.     ng.ng_TopEdge    = win->screen->WBorTop + win->screen->RastPort.TxHeight + VSPACE;
  266.     ng.ng_Width      = ((win->win->Width * 2)/3) - ng.ng_LeftEdge;
  267.     ng.ng_GadgetID   = nID++;
  268.     ng.ng_Flags     = PLACETEXT_LEFT;
  269.     win->ServerString = gad = CreateGadget(STRING_KIND, gad, &ng, GTST_String, szCurrentHostname, GT_Underscore, '_', TAG_END);
  270.  
  271.     /* Allocate Port gadget */
  272.     ng.ng_GadgetText = PORT_STRING_TEXT;
  273.     ng.ng_LeftEdge   += ng.ng_Width + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
  274.     ng.ng_Width      = win->win->Width - ng.ng_LeftEdge - win->screen->WBorRight - HSPACE;
  275.     ng.ng_GadgetID   = nID++;
  276.     ng.ng_Flags     = PLACETEXT_LEFT;
  277.     win->PortString = gad = CreateGadget(INTEGER_KIND, gad, &ng, GTIN_Number, nPort, GT_Underscore, '_', TAG_END);
  278.     
  279.     /* Allocate Comment gadget */
  280.     ng.ng_GadgetText = COMMENT_STRING_TEXT;
  281.     ng.ng_LeftEdge   = win->screen->WBorLeft + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
  282.     ng.ng_TopEdge    += ng.ng_Height + VSPACE;
  283.     ng.ng_Width      = win->win->Width - ng.ng_LeftEdge - win->screen->WBorRight - HSPACE;
  284.     ng.ng_GadgetID   = nID++;
  285.     ng.ng_Flags     = PLACETEXT_LEFT;
  286.     win->CommentString = gad = CreateGadget(STRING_KIND, gad, &ng, GTST_String, szCurrentComment, GT_Underscore, '_', TAG_END);
  287.  
  288.     /* Allocate Update button */
  289.     ng.ng_GadgetText = UPDATE_BUTTON_TEXT;
  290.     ng.ng_TopEdge    += ng.ng_Height + VSPACE;
  291.     ng.ng_LeftEdge   = win->screen->WBorLeft + HSPACE;
  292.     ng.ng_Width      = TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + HSPACE;
  293.     ng.ng_Flags     = PLACETEXT_IN;
  294.     ng.ng_GadgetID   = nID++;
  295.     win->UpdateButton = gad = CreateGadget(BUTTON_KIND, gad, &ng, GT_Underscore, '_', TAG_END);
  296.  
  297.     /* Allocate UpdateInterval string */
  298.     ng.ng_GadgetText = EVERY_TEXT;
  299.     ng.ng_LeftEdge   += ng.ng_Width + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
  300.     ng.ng_Width      = TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + HSPACE;
  301.     ng.ng_Flags     = PLACETEXT_LEFT;
  302.     ng.ng_GadgetID   = nID++;
  303.     win->UpdateIntString = gad = CreateGadget(INTEGER_KIND, gad, &ng, GTIN_Number, nRefreshInterval, GT_Underscore, '_', TAG_END);
  304.  
  305.     /* Allocate Mins text */
  306.     ng.ng_GadgetText = MINS_TEXT1;
  307.     ng.ng_Flags     = PLACETEXT_LEFT;
  308.     ng.ng_LeftEdge   += ng.ng_Width + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3); 
  309.     ng.ng_Width      = 0;
  310.     ng.ng_GadgetID   = nID++;
  311.     gad = CreateGadget(TEXT_KIND, gad, &ng, GT_Underscore, '_', TAG_END);
  312.  
  313.     /* Allocate Ping button */
  314.     ng.ng_GadgetText = PING_BUTTON_TEXT;
  315.     ng.ng_Width      = TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + HSPACE;
  316.     ng.ng_Flags     = PLACETEXT_IN;
  317.     ng.ng_GadgetID   = nID++;
  318.     win->PingButton  = gad = CreateGadget(BUTTON_KIND, gad, &ng, GT_Underscore, '_', TAG_END);
  319.  
  320.     /* Allocate PingInterval string */
  321.     ng.ng_GadgetText = EVERY_TEXT;
  322.     ng.ng_LeftEdge   += ng.ng_Width + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3);
  323.     ng.ng_Width      = TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + HSPACE;
  324.     ng.ng_Flags     = PLACETEXT_LEFT;
  325.     ng.ng_GadgetID   = nID++;
  326.     win->PingIntString = gad = CreateGadget(INTEGER_KIND, gad, &ng, GTIN_Number, nPingInterval, GT_Underscore, '_', TAG_END);
  327.  
  328.     /* Allocate Mins2 text */
  329.     ng.ng_GadgetText = MINS_TEXT2;
  330.     ng.ng_Flags     = PLACETEXT_LEFT;
  331.     ng.ng_LeftEdge   += ng.ng_Width + TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + (HSPACE*3); 
  332.     ng.ng_Width      = TextLength(&win->screen->RastPort, ng.ng_GadgetText, strlen(ng.ng_GadgetText)) + HSPACE;
  333.     ng.ng_GadgetID   = nID++;
  334.     gad = CreateGadget(TEXT_KIND, gad, &ng, GT_Underscore, '_', TAG_END);
  335.     
  336.     /* Allocate ListView */
  337.     ng.ng_GadgetText = NULL;
  338.     ng.ng_TextAttr   = &win->fixedfont;
  339.     ng.ng_LeftEdge   = win->screen->WBorLeft + HSPACE;
  340.     ng.ng_TopEdge    += ng.ng_Height + VSPACE;
  341.     ng.ng_Width     = win->win->Width - ng.ng_LeftEdge - win->screen->WBorRight - HSPACE;
  342.     ng.ng_Height     = win->win->Height - ng.ng_TopEdge - win->screen->WBorBottom - (VSPACE*2);
  343.     win->ListGadget = gad = CreateGadget(LISTVIEW_KIND, gad, &ng, GTLV_ReadOnly, TRUE, GTLV_Labels, win->DisplayList, TAG_END);
  344.  
  345.     /* Attach gadgets to window */    
  346.     AddGList(win->win, win->glist, -1, -1, NULL);
  347.     RefreshGList(win->glist, win->win, NULL, -1);
  348.     GT_RefreshWindow(win->win, NULL);
  349.  
  350.     return(TRUE);
  351. }
  352.  
  353.  
  354. void AttachList(struct WindowStuff * win, BOOL BAttach)
  355. {
  356.     if ((win->win)&&(win->ListGadget)) 
  357.     {
  358.         GT_SetGadgetAttrs(win->ListGadget, win->win, NULL, 
  359.             GTLV_Labels, (((BAttach)&&(win->DisplayList)) 
  360.             ? win->DisplayList : ((struct List *)(~0))), TAG_END);
  361.     }
  362. }
  363.  
  364. /* Disables some gadgets if we aren't properly connected */
  365. void SetConnectStatus(struct WindowStuff * win, BOOL BNewStatus)
  366. {
  367.     /* If we're not connected, might as well ditch our list */
  368.     if ((win->ListGadget)&&(win->DisplayList)&&(BNewStatus == FALSE))
  369.     {
  370.         AttachList(win, TRUE);
  371.         if (win->DisplayList) FreeDisplayList(win->DisplayList);
  372.         win->DisplayList = NULL;
  373.         AttachList(win, FALSE);
  374.     }            
  375.     if (win->PingButton)   GT_SetGadgetAttrs(win->PingButton,   win->win, NULL, GA_Disabled, !BNewStatus);
  376.     if (win->UpdateButton) GT_SetGadgetAttrs(win->UpdateButton, win->win, NULL, GA_Disabled, !BNewStatus);
  377.     BSendGoodbye = BNewStatus;
  378. }
  379.  
  380.  
  381.  
  382.  
  383.  
  384. /* Returns any additional action flags that we want set */
  385. ULONG HandleIDCMP(struct WindowStuff * win)
  386. {
  387.     struct IntuiMessage *message;
  388.     ULONG class, code, qual, ulItemCode, ulFlags = 0L;
  389.     struct Gadget * gad;
  390.     struct MenuItem * mItem;
  391.     
  392.     /* Examine pending messages */    
  393.     while (message = (struct IntuiMessage *)GetMsg(win->win->UserPort))
  394.     {
  395.         class = message->Class;        /* extract needed info from message */
  396.         code  = message->Code;
  397.         gad   = (struct Gadget *) message->IAddress;
  398.         qual  = message->Qualifier;
  399.  
  400.         /* tell Intuition we got the message */
  401.         ReplyMsg((struct Message *)message);
  402.  
  403.         /* see what events occured, take correct action */
  404.         switch(class)
  405.         {        
  406.             case IDCMP_CLOSEWINDOW: 
  407.                 TrackExit("Window closed", RETURN_OK);
  408.                 break;
  409.  
  410.                   case IDCMP_NEWSIZE:
  411.                       UpdateWindow(win,FALSE);
  412.                       break;
  413.           
  414.                   case IDCMP_INTUITICKS:
  415.                       break;
  416.                   
  417.                   case IDCMP_MOUSEBUTTONS:
  418.                       break;
  419.                       
  420.             case IDCMP_VANILLAKEY: 
  421.                 switch(code)
  422.                 {
  423.                     case 'p': case 'P': ulFlags |= CODE_PING;    break;
  424.                     case 'r': case 'R': ulFlags |= CODE_REFRESH; break;
  425.                     case 's': case 'S': ActivateGadget(win->ServerString, win->win, NULL);    break;
  426.                     case 'o': case 'O': ActivateGadget(win->PortString, win->win, NULL);      break;
  427.                     case 'c': case 'C': ActivateGadget(win->CommentString, win->win, NULL);   break;
  428.                     case 'm': case 'M': ActivateGadget(win->UpdateIntString, win->win, NULL); break;
  429.                     case 'i': case 'I': ActivateGadget(win->PingIntString, win->win, NULL);   break;
  430.                 }
  431.                 break;
  432.                 
  433.             case IDCMP_GADGETUP:
  434.                       if (gad == win->ListGadget)    {/* printf("ListGadget\n");*/}
  435.                      else if (gad == win->PingButton)        ulFlags |= CODE_PING;
  436.                      else if (gad == win->CommentString)
  437.                           {
  438.                               char * szTemp = NULL;
  439.                               
  440.                               /* Grab and sanitize the new comment */
  441.                     ReplaceAllocedString(&szTemp,((struct StringInfo*)win->CommentString->SpecialInfo)->Buffer);
  442.                     ReplaceAllocedString(&szCurrentComment, PastSpaces(RemoveUnprintableChars(szTemp)));
  443.                     ReplaceAllocedString(&szTemp, NULL);
  444.                     GT_SetGadgetAttrs(win->CommentString, win->win, NULL, GTST_String, szCurrentComment);
  445.  
  446.                     ulFlags |= CODE_PING;
  447.                     AttachList(win,FALSE);
  448.                     PatchDisplayList(win->DisplayList, ulMyIPAddress, szMyHostName, szCurrentComment);
  449.                     AttachList(win,TRUE);
  450.                           }
  451.                      else if (gad == win->ServerString)       
  452.                           {
  453.                               char * szTemp = NULL;
  454.                               
  455.                               /* Grab and sanitize the new server string */
  456.                     ReplaceAllocedString(&szTemp,((struct StringInfo*)win->ServerString->SpecialInfo)->Buffer);
  457.                     ReplaceAllocedString(&szCurrentHostname, ToLower(PastSpaces(RemoveUnprintableChars(szTemp))));
  458.                     ReplaceAllocedString(&szTemp, NULL);
  459.                               UNLESS(strcmp(szCurrentHostname,"localhost")) ReplaceAllocedString(&szCurrentHostname, szMyHostName); 
  460.                               GT_SetGadgetAttrs(win->ServerString, win->win, NULL, GTST_String, szCurrentHostname);
  461.                     ulFlags |= CODE_RECONNECT;
  462.                           }
  463.                      else if (gad == win->PortString)       
  464.                           {
  465.                     nPort = ((struct StringInfo*)win->PortString->SpecialInfo)->LongInt;
  466.                     if (nPort == 0) 
  467.                     {
  468.                         nPort = SERVER_TCP_PORT;
  469.                         GT_SetGadgetAttrs(win->PortString, win->win, NULL, GTIN_Number, nPort);
  470.                     }
  471.                               ulFlags |= CODE_RECONNECT;
  472.                           }
  473.                      else if (gad == win->UpdateButton)       ulFlags |= CODE_REFRESH;
  474.                      else if (gad == win->UpdateIntString)    
  475.                      {
  476.                          nRefreshCount = nRefreshInterval = ((struct StringInfo*)win->UpdateIntString->SpecialInfo)->LongInt;
  477.                      }
  478.                      else if (gad == win->PingIntString)    
  479.                      {
  480.                          nPingCount = nPingInterval = ((struct StringInfo*)win->PingIntString->SpecialInfo)->LongInt;
  481.                      }
  482.                      /* else printf("unknown gadget %p\n",gad); */
  483.  
  484.                                 break;
  485.  
  486.             case IDCMP_MENUPICK:
  487.                 while( code != MENUNULL ) 
  488.                 {
  489.                     char szMessage[150];
  490.                     mItem = ItemAddress( Menu, code );
  491.                     
  492.                     ulItemCode = (ULONG) GTMENUITEM_USERDATA(mItem);
  493.                     switch(ulItemCode)
  494.                     {
  495.                         case P_ICONIFY:
  496.                             ulFlags |= CODE_ICONIFY;
  497.                             break;
  498.                             
  499.                         case P_ABOUT:        
  500.                             sprintf(szMessage,"%s\nby Jeremy Friesner\njfriesne@ucsd.edu\nCompiled: %s",
  501.                                 pcDisplayVersionString,__DATE__);
  502.                             MakeReq(NULL,szMessage,"Not Bad");
  503.                             break;
  504.                         case P_QUIT:        TrackExit("Quit requested",RETURN_OK);    break;
  505.                     }
  506.                     code = mItem->NextSelect;
  507.                 }
  508.                 break;
  509.             
  510.             case IDCMP_REFRESHWINDOW:
  511.                 GT_BeginRefresh(win->win);
  512.                 GT_EndRefresh(win->win, TRUE);
  513.                 break;
  514.                        
  515.             default:        
  516.                 /* printf("handleIDCMP: bad class %lu\n",class); */
  517.                 break;
  518.         }
  519.     }
  520.     return(ulFlags);
  521. }
  522.  
  523.  
  524. /* Searches the given DisplayList until it finds a string beginning with
  525.    szReplaceMe.  It then deletes that node and replaces it with an
  526.    entry composed of the params */
  527. void PatchDisplayList(struct List * DisplayList, ULONG ulIPAddress, char * szReplaceMe, char * szNewComment)
  528. {
  529.     struct Node * current, * prev = NULL, * newNode;
  530.     char * pcTemp, * pcSpace;
  531.     int nLen = strlen(szReplaceMe);
  532.     ULONG ulThisIPAddress;
  533.  
  534.     UNLESS(DisplayList) return;
  535.     current = DisplayList->lh_Head;
  536.     while(current->ln_Succ)
  537.     {
  538.         if (pcTemp = (char *)current->ln_Name)
  539.         {
  540.             ulThisIPAddress = (ULONG) *((ULONG *) (current->ln_Name-sizeof(ULONG)-sizeof(ULONG)));
  541.             if (ulIPAddress == ulThisIPAddress)
  542.             {
  543.                 /* Figure out the correct padding from the old one */
  544.                 UNLESS(pcSpace = strchr(pcTemp,' ')) return;
  545.                 while(*pcSpace == ' ') pcSpace++;
  546.                 if (newNode = AllocDisplayItem(szReplaceMe, ulIPAddress, ((int)(pcSpace-pcTemp))-1, szNewComment))
  547.                 {
  548.                     Remove(current);
  549.                     Insert(DisplayList, newNode, prev);
  550.                     FreeDisplayItem(current);
  551.                 }
  552.                 return;                
  553.             }
  554.         }
  555.         prev = current;
  556.         current = current->ln_Succ;
  557.     }
  558. }
  559.  
  560.  
  561. struct WindowStuff * SetupTrackWindow(struct WindowStuff * win)
  562. {
  563.     if (win)
  564.     {
  565.         /* Free the window */
  566.         UpdateWindow(win,TRUE);    /* Free all the gadgets */
  567.         if (win->DisplayList)     FreeDisplayList(win->DisplayList);
  568.         if (win->fontdata)     CloseFont(win->fontdata);
  569.         if (win->fixedfontdata)    CloseFont(win->fixedfontdata);
  570.         if (win->win)        CloseWindow(win->win);
  571.         if (win->screen)     UnlockPubScreen(NULL,win->screen);
  572.         
  573.         FreeMem(win,sizeof(struct WindowStuff));
  574.         return(NULL);
  575.     }
  576.     else
  577.     {
  578.         UNLESS(win = AllocMem(sizeof(struct WindowStuff), MEMF_CLEAR)) return(NULL);
  579.         
  580.         /* Find the default public screen */
  581.  
  582.         UNLESS(win->screen = LockPubScreen(NULL)) return(SetupTrackWindow(win));
  583.  
  584.         AskFont(&win->screen->RastPort, &win->font);
  585.          UNLESS(win->fontdata = OpenDiskFont(&win->font)) return(SetupTrackWindow(win));
  586.  
  587.         nMinWinHeight = win->screen->WBorTop + win->screen->RastPort.TxHeight + VSPACE + 3*(win->font.ta_YSize + VSPACE + VSPACE) + win->screen->WBorBottom + VSPACE;
  588.         nMinWinWidth  = win->screen->WBorLeft + TextLength(&win->screen->RastPort, ALL_BOTTOM_LINE_TEXT, strlen(ALL_BOTTOM_LINE_TEXT)) + (HSPACE * 25) + win->screen->WBorRight;
  589.         
  590.         /* Open the window */
  591.         UNLESS(win->win = OpenWindowTags(NULL,
  592.          WA_Left,        nWinLeft,
  593.          WA_Top,        nWinTop,
  594.          WA_Width,        nMinWinWidth,
  595.          WA_Height,        nMinWinHeight * 2,
  596.          WA_MinWidth,        nMinWinWidth,
  597.          WA_MinHeight,        nMinWinHeight,
  598.          WA_PubScreen,        win->screen,
  599.          WA_PubScreenFallBack, TRUE,
  600.          WA_MaxWidth,        -1,
  601.          WA_MaxHeight,        -1,
  602.          WA_Title,        pcDisplayVersionString, 
  603.          WA_CloseGadget,    TRUE,
  604.          WA_DepthGadget,    TRUE,
  605.          WA_SizeGadget,     TRUE,
  606.          WA_Activate,        TRUE,
  607.          WA_DragBar,        TRUE,
  608.          WA_SizeBBottom,    TRUE,
  609.              WA_IDCMP,       IDCMP_REFRESHWINDOW | IDCMP_CLOSEWINDOW | 
  610.                   IDCMP_MENUPICK | IDCMP_NEWSIZE | IDCMP_VANILLAKEY |
  611.                   BUTTONIDCMP | LISTVIEWIDCMP | STRINGIDCMP,
  612.          TAG_DONE)) return(SetupTrackWindow(win));
  613.  
  614.         AskFont(win->win->RPort, &win->fixedfont);
  615.          UNLESS(win->fixedfontdata = OpenDiskFont(&win->fixedfont)) return(SetupTrackWindow(win));
  616.  
  617.         UNLESS(UpdateWindow(win,FALSE)) return(SetupTrackWindow(win));
  618.         return(win);
  619.     }
  620. }
  621.  
  622.  
  623. /* Creates a DisplayList from a ClientList.  
  624.    In a DisplayList, each item is an ASCII string.
  625.    There is a ULONG directly before the beginning of each string, 
  626.    giving the string's length. */
  627. struct List * CreateDisplayList(struct ClientList * oldlist)
  628. {
  629.     ULONG ulMaxHostnameLength = 0, ulTemp;
  630.     struct Client * client;
  631.     struct List * newlist;
  632.     struct Node * newnode;
  633.     
  634.     UNLESS(oldlist) return(NULL);
  635.     
  636.     /* First allocate our new list header */
  637.     UNLESS(newlist = AllocMem(sizeof(struct List), MEMF_CLEAR)) return(NULL);
  638.     NewList(newlist);
  639.  
  640.     /* first find out the length of the longest hostname in the ClientList */
  641.     client = (struct Client *) oldlist->list.lh_Head;
  642.     while(client->node.ln_Succ)
  643.     {
  644.         ulTemp = strlen(client->hostname);
  645.         if (ulTemp > ulMaxHostnameLength) ulMaxHostnameLength = ulTemp;
  646.         client = (struct Client *)client->node.ln_Succ;
  647.     }
  648.  
  649.     /* Now construct the DisplayList, with hostnames padded out appropriately */
  650.     client = (struct Client *) oldlist->list.lh_Head;
  651.     while(client->node.ln_Succ)
  652.     {
  653.         UNLESS(newnode = AllocDisplayItem(client->hostname, client->ulIPAddress, ulMaxHostnameLength, client->comment)) return(newlist);
  654.         AddTail(newlist, newnode);
  655.         client = (struct Client *)client->node.ln_Succ;
  656.     }
  657.     return(newlist);
  658. }
  659.  
  660.  
  661. struct Node * AllocDisplayItem(char * szHostName, ULONG ulIPAddress, ULONG ulHostFieldLen, char * szComment)
  662. {
  663.     struct Node * newnode;
  664.     UBYTE * pubData;
  665.     ULONG ulAllocLength = ulHostFieldLen + strlen(szComment) + 2;    /* 2 == space plus NUL */
  666.     char * pcTemp, * pcTemp2;
  667.     
  668.     UNLESS(newnode = AllocMem(sizeof(struct Node), MEMF_ANY)) return(NULL);
  669.     UNLESS(pubData = AllocMem(ulAllocLength + sizeof(ULONG) + sizeof(ULONG), MEMF_ANY))
  670.     {
  671.         FreeMem(newnode, sizeof(struct Node));
  672.         return(NULL);
  673.     }
  674.     memcpy(pubData, &ulIPAddress,   sizeof(ULONG));    
  675.     pubData += sizeof(ULONG);    /* Ignore the IPAddress ULONG from now on... */
  676.     memcpy(pubData, &ulAllocLength, sizeof(ULONG));
  677.     pubData += sizeof(ULONG);    /* Ignore the memalloced ULONG from now on... */
  678.     memset(pubData, ' ', ulHostFieldLen+1);
  679.     
  680.     /* like strcpy but without copying the NUL terminal! */
  681.     pcTemp = pubData; pcTemp2 = szHostName;
  682.     while(*pcTemp2)
  683.     {
  684.         *pcTemp = *pcTemp2;
  685.         pcTemp++; pcTemp2++;
  686.     }    
  687.     strcpy(&pubData[ulHostFieldLen+1], szComment);
  688.     newnode->ln_Name = pubData;
  689.     return(newnode);
  690. }
  691.  
  692.  
  693. void FreeDisplayItem(struct Node * victim)
  694. {
  695.     ULONG ulLen;
  696.  
  697.     memcpy(&ulLen, victim->ln_Name-sizeof(ULONG), sizeof(ULONG));
  698.     FreeMem(victim->ln_Name-sizeof(ULONG)-sizeof(ULONG), ulLen+sizeof(ULONG)+sizeof(ULONG));
  699.     FreeMem(victim,sizeof(struct Node));
  700. }
  701.  
  702.  
  703. /* Frees an allocated DisplayList. */
  704. void FreeDisplayList(struct List * list)
  705. {
  706.     struct Node * current;
  707.     
  708.     UNLESS(list) return;    
  709.     while(current = RemHead(list)) FreeDisplayItem(current);
  710.     FreeMem(list, sizeof(struct List));
  711. }
  712.  
  713.  
  714. void debug(int n)
  715. {
  716.     printf("enter debug %i ... ",n); fflush(stdout);
  717.     Delay(50);
  718.     printf("continuing.\n"); fflush(stdout);
  719. }
  720.  
  721. VOID wbmain(struct WBStartup *wbargv)
  722. {
  723.     BStartedFromWB = TRUE;
  724.     main(0,NULL);
  725. }
  726.  
  727. int main(int argc, char **argv)
  728. {
  729.     if ((argc == 2)&&(strcmp(argv[1],"?")==0))
  730.     {
  731.         printf("Usage:  AmiTrack [ServerName] [Comment] [Port]\n");
  732.         exit(5);
  733.     }
  734.     atexit(Cleanup);
  735.  
  736.     pcDisplayVersionString = &szVersionString[6];
  737.     BeAClient((argc>=2) ? argv[1] : DEFAULT_AMITRACK_SERVER, (argc>=3) ? argv[2] : NULL, (argc>=4) ? atoi(argv[3]) : SERVER_TCP_PORT);
  738. }
  739.  
  740.  
  741.  
  742. /* Always called when AmiTrack exits, does any necessary cleanup */
  743. void Cleanup(void)
  744. {
  745.     ReplaceAllocedString(&szCurrentHostname, NULL);
  746.     ReplaceAllocedString(&szCurrentComment,  NULL);
  747.  
  748.     if (UDPSocket) 
  749.     {
  750.         if (BSendGoodbye) SendPacket(UDPSocket, REQ_BYE, NULL);
  751.         SetupSocket(UDPSocket,0,0);
  752.     }
  753.     if (Timer) SetupTimer(Timer);
  754.     if (SocketBase) CloseLibrary(SocketBase);
  755.  
  756.  
  757.     if (TrackWindow)   SetupTrackWindow(TrackWindow);
  758.     if (DiskFontBase)  CloseLibrary(DiskFontBase);
  759.     if (GadToolsBase)  CloseLibrary(GadToolsBase);
  760.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  761.     if (GraphicsBase)  CloseLibrary(GraphicsBase);
  762.     if (WorkbenchBase) CloseLibrary(WorkbenchBase);
  763.     if (IconBase)      CloseLibrary(IconBase);
  764. }
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772. /* Act like a client.  Connect to szHostName, register yourself
  773.    with this Amiga's IP address, and the given szComment. */
  774. void BeAClient(char * szHostName, char * szComment, int nPortPref)
  775. {
  776.     int nCode;
  777.     struct hostent * localhostent;
  778.  
  779.     UNLESS(SocketBase = OpenLibrary("bsdsocket.library", 2))
  780.         TrackExit("Couldn't open socket.library v2+ (is AmiTCP running?)", RETURN_ERROR);
  781.  
  782.     gethostname(szMyHostName, sizeof(szMyHostName));
  783.     if ((szHostName)&&(strcmp(szHostName,"localhost") == 0)) szHostName = szMyHostName;
  784.     localhostent = gethostbyname(szMyHostName);
  785.     if ((localhostent)&&(localhostent->h_addr_list[0]))
  786.         ulMyIPAddress = (ULONG) *((ULONG *)localhostent->h_addr_list[0]);
  787.  
  788.     /* Allocate our own copies of the given strings */
  789.     if (strlen(szHostName) > 0) ReplaceAllocedString(&szCurrentHostname, szHostName);
  790.     ReplaceAllocedString(&szCurrentComment,  szComment);
  791.     nPort = nPortPref;
  792.  
  793.     UNLESS(Timer = SetupTimer(NULL)) 
  794.         TrackExit("Couldn't setup timer.device.",RETURN_ERROR);
  795.                     
  796.     UNLESS(WorkbenchBase = OpenLibrary("workbench.library",37))
  797.         TrackExit("Couldn't open icon.library 37+",RETURN_ERROR);
  798.  
  799.     UNLESS(IconBase = OpenLibrary("icon.library",33))
  800.         TrackExit("Couldn't open icon.library 33+",RETURN_ERROR);
  801.  
  802.     UNLESS(GraphicsBase = OpenLibrary("graphics.library", 37))
  803.         TrackExit("Couldn't open graphics.library 37+",RETURN_ERROR);
  804.  
  805.     UNLESS(IntuitionBase = OpenLibrary("intuition.library", 37))
  806.         TrackExit("Couldn't open intuition.library 37+",RETURN_ERROR);
  807.  
  808.     UNLESS(GadToolsBase = OpenLibrary("gadtools.library", 37))
  809.         TrackExit("Couldn't open gadtools.library 37+",RETURN_ERROR);
  810.  
  811.     UNLESS(DiskFontBase = OpenLibrary("diskfont.library", 37))
  812.         TrackExit("Couldn't open diskfont.library 37+",RETURN_ERROR);
  813.  
  814.     UNLESS(TrackWindow = SetupTrackWindow(NULL))
  815.         TrackExit("Couldn't open GUI", RETURN_ERROR);
  816.  
  817.     UNLESS(UDPSocket = SetupSocket(NULL,0,SOCK_DGRAM)) 
  818.         TrackExit("Couldn't open UDP Socket.",RETURN_ERROR);
  819.  
  820.     if (szCurrentHostname)
  821.     {
  822.         char szMessage[100];
  823.     
  824.         sprintf(szMessage,"Connecting to [%s], port %i",szCurrentHostname, nPort);
  825.         StatMessage(szMessage);
  826.     
  827.         if (ConnectToServer(TrackWindow, UDPSocket, szCurrentHostname)) 
  828.         {
  829.             PingServer(TrackWindow, UDPSocket, szCurrentComment);
  830.             Signal(FindTask(NULL),SIGBREAKF_CTRL_D);    /* Cause myself to show the client list */
  831.         }
  832.     }
  833.     SetTimer(Timer, 60, 0);
  834.     SetConnectStatus(TrackWindow, FALSE);        /* Default to not connected yet */
  835.     
  836.     while(nCode = TrackWait(NULL, NULL, Timer, TrackWindow, NULL))
  837.     {
  838.         if (nCode & CODE_WINDOW_EVENT) nCode |= HandleIDCMP(TrackWindow);
  839.         if (nCode & CODE_REFRESH)
  840.         {
  841.             char szMessage[100];
  842.             struct ClientList * test;
  843.  
  844.             if (szCurrentHostname)
  845.             {
  846.                 sprintf(szMessage,"Trying to get login list from %s.",szCurrentHostname);
  847.                 StatMessage(szMessage);
  848.             }
  849.             
  850.             if (test = GetTrackList(szCurrentHostname, nPort))
  851.             {
  852.                  AttachList(TrackWindow, FALSE);
  853.                  if (TrackWindow->DisplayList) FreeDisplayList(TrackWindow->DisplayList);
  854.                  TrackWindow->DisplayList = CreateDisplayList(test);
  855.                  AttachList(TrackWindow, TRUE);
  856.                  SetupClientList(test);
  857.                  SetConnectStatus(TrackWindow, TRUE);
  858.                  StatMessage("Login list refreshed.");
  859.             }
  860.             else 
  861.             {
  862.                 
  863.                  StatMessage("Couldn't get login list from server.");
  864.                  SetConnectStatus(TrackWindow, FALSE);
  865.             }
  866.         }
  867.         if (nCode & CODE_RECONNECT)
  868.         {
  869.             char szMessage[100];
  870.  
  871.             if (BSendGoodbye) SendPacket(UDPSocket, REQ_BYE, NULL);
  872.             BSendGoodbye = FALSE;
  873.             SetupSocket(UDPSocket,0,0);    
  874.  
  875.             UNLESS(UDPSocket = SetupSocket(NULL,0,SOCK_DGRAM)) 
  876.                 TrackExit("Couldn't reopen UDP Socket.",RETURN_ERROR);
  877.  
  878.             sprintf(szMessage,"Connecting to [%s], port %i",szCurrentHostname, nPort);
  879.             StatMessage(szMessage);
  880.             
  881.             if (ConnectToServer(TrackWindow, UDPSocket, szCurrentHostname))
  882.             { 
  883.                 sprintf(szMessage,"Connected to %s:%i",szCurrentHostname,nPort);
  884.                 StatMessage(szMessage);
  885.                 PingServer(TrackWindow, UDPSocket, szCurrentComment);
  886.                 Signal(FindTask(NULL),SIGBREAKF_CTRL_D);
  887.             }
  888.             else
  889.             {
  890.                 
  891.                  if (szCurrentHostname)
  892.                  {
  893.                      sprintf(szMessage,"Couldn't connect to %s:%i",szCurrentHostname, nPort);
  894.                      StatMessage(szMessage);
  895.                  }
  896.                  SetConnectStatus(TrackWindow,FALSE);
  897.             }
  898.         }
  899.         if (nCode & CODE_PING)         PingServer(TrackWindow, UDPSocket, szCurrentComment);
  900.         if (nCode & CODE_TIMER_EXPIRED) DoPeriodicUpdates(TrackWindow, UDPSocket, Timer);
  901.         if (nCode & CODE_ICONIFY)     TrackWindow = Hibernate(TrackWindow, UDPSocket, Timer);
  902.     }
  903. }
  904.  
  905.  
  906. /* Handle the pings and updates and so on */
  907. void DoPeriodicUpdates(struct WindowStuff * win, struct SocketStuff * sSocket, struct TimerStuff * timer)
  908. {
  909.     if ((nPingInterval > 0)&&((--nPingCount) <= 0))
  910.     {
  911.         PingServer(win, sSocket, szCurrentComment);
  912.         nPingCount = nPingInterval;
  913.     }
  914.     if ((nRefreshInterval > 0)&&((--nRefreshCount) <= 0))
  915.     {
  916.         Signal(FindTask(NULL),SIGBREAKF_CTRL_D);    /* Cause myself to show the client list */
  917.         nRefreshCount = nRefreshInterval;
  918.     }
  919.     SetTimer(timer, 60, 0);
  920. }
  921.         
  922.  
  923. /* Returns FALSE on too many errors, TRUE otherwise */
  924. BOOL PingServer(struct WindowStuff * win, struct SocketStuff * sSocket, char * szComment)
  925. {
  926.     static int nNumErrors;
  927.         
  928.     if (SendPacket(sSocket, REQ_COMMENT, szComment)) 
  929.     {
  930.         if (nNumErrors >= MAX_PING_ERRORS)
  931.              {
  932.             StatMessage("Server ping recovered!");
  933.              SetConnectStatus(TrackWindow, TRUE);
  934.              }
  935.              nNumErrors = 0;
  936.     }
  937.     else if (nNumErrors++ == MAX_PING_ERRORS)
  938.     {
  939.             
  940.             StatMessage("Error:  Server ping timeout");
  941.              SetConnectStatus(TrackWindow, FALSE);
  942.             return(FALSE);
  943.     }         
  944.     return(TRUE);
  945. }
  946.  
  947.  
  948. /* Sends a UDP packet to the server.  The first byte
  949.    of the packet is a control byte, after that there
  950.    is just the NULL-terminated string szComment. */
  951. BOOL SendPacket(struct SocketStuff * sSocket, ULONG ulReqs, char * szComment)
  952. {
  953.     int nBufLen;
  954.     char * pcBuf;
  955.     BOOL BRet;
  956.  
  957.     UNLESS(szComment) szComment = "";
  958.     nBufLen = sizeof(ULONG) + strlen(szComment) + 1;
  959.     
  960.     /* Allocate and fill out the transfer buffer */
  961.     UNLESS(pcBuf = (char *)AllocMem(nBufLen, MEMF_ANY)) return(FALSE);
  962.     memcpy(&pcBuf[0], &ulReqs, sizeof(ULONG));
  963.     strcpy(&pcBuf[sizeof(ULONG)], szComment);
  964.     BRet = (send(sSocket->fd, (UBYTE *)pcBuf, nBufLen, 0L) == nBufLen);
  965.     FreeMem(pcBuf, nBufLen);
  966.     return(BRet);
  967. }
  968.  
  969.  
  970.  
  971. /* Used by the client.  Note that this connect() call probably 
  972.    won't fail even if the server IS running on the host named
  973.    szPeerName, because UDP sockets are connectionless, and connect()
  974.    does nothing but affect an AmiTCP-internal setting that governs
  975.    where send() will send to when used on this socket.  Rather,
  976.    if something goes wrong, subsequent send() calls will return
  977.    errors instead. */
  978. BOOL ConnectToServer(struct WindowStuff * win, struct SocketStuff * sSocket, char * szPeerName)
  979. {
  980.     struct hostent * hp;
  981.     char szMessage[100];
  982.  
  983.     UNLESS(szPeerName) return(FALSE);    
  984.     UNLESS(hp = gethostbyname(szPeerName))
  985.     {
  986.         sprintf(szMessage, "Name lookup failed for server [%s]",szPeerName);
  987.         StatMessage(szMessage);
  988.         return(FALSE);
  989.     }
  990.     bzero(&sSocket->saAddr, sizeof(struct sockaddr_in));
  991.         bcopy(hp->h_addr, (char *)&sSocket->saAddr.sin_addr, hp->h_length);
  992.     sSocket->saAddr.sin_port   = htons(nPort);
  993.     sSocket->saAddr.sin_family = hp->h_addrtype;
  994.  
  995.     UNLESS(connect(sSocket->fd, (struct sockaddr *) &sSocket->saAddr, sizeof(struct sockaddr_in)) >= 0)
  996.     {
  997.         sprintf(szMessage,"Connect to [%s] failed.",szPeerName);
  998.         StatMessage(szMessage);
  999.         return(FALSE);
  1000.     }
  1001.     return(TRUE);
  1002. }
  1003.  
  1004. void StatMessage(char * message)
  1005. {
  1006.     static char szMessage[100];
  1007.     
  1008.     strncpy(szMessage,message,sizeof(szMessage));
  1009.     szMessage[99] = 0;
  1010.         
  1011.     if ((TrackWindow)&&(TrackWindow->win)) SetWindowTitles(TrackWindow->win, szMessage, (char *)~0);
  1012. }